package com.ymatou.iapi.settlement.testcase;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;

import org.apache.http.client.ClientProtocolException;
import org.json.JSONArray;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.categories.Category;

import com.ymatou.iapi.settlement.parameter.GenerateRefundCommissionInvoiceBean;
import com.ymatou.iapi.settlement.parameter.OrderSettlementReq;
import com.ymatou.iapi.settlement.parameter.SettleSellerIncomeAndChargeCommissionBean;
import com.ymatou.iapi.settlement.service.GenerateInvoicesOnOrderReceivedCall;
import com.ymatou.iapi.settlement.service.GenerateRefundCommissionInvoiceCall;
import com.ymatou.iapi.settlement.service.SettleSellerIncomeAndChargeCommissionCall;
import com.ymatou.iapi.settlement.service.SettlementService;
import com.ymatou.iapi.trading.operate.parameter.Order;
import com.ymatou.iapi.trading.operate.parameter.OrderInfoPo;
import com.ymatou.iapi.trading.operate.parameter.OrderItemVo;
import com.ymatou.iapi.trading.operate.parameter.PlaceOrderResp;
import com.ymatou.iapi.trading.operate.parameter.PlaceOrderService;
import com.ymatou.iapi.trading.operate.parameter.req.ApplySalesRefundRequestBean;
import com.ymatou.iapi.trading.operate.parameter.req.PlaceOrderReq;
import com.ymatou.iapi.trading.operate.parameter.req.SalesRefundInfoBean;
import com.ymatou.iapi.trading.operate.service.ApplySalesRefundRequestCall;
import com.ymatou.iapi.trading.operate.service.PlaceOrderCall;
import com.ymt.core.tool.Logger;
import com.ymt.utils.annotation.TestCase;
import com.ymt.utils.annotation.TestSuite;
import com.ymt.utils.tag.P1;
import com.ymttest.business.service.OrderCallService;
import com.ymttest.database.model.YmtCommissionDetail;
import com.ymttest.database.sqlwapper.AccountDefaultWapper;
import com.ymttest.database.sqlwapper.DefaultWapper;
import com.ymttest.database.sqlwapper.YmtCommissionDetailWapper;
import com.ymttest.database.sqlwapper.YmtRefundWapper;
import com.ymttest.utils.EnvSetup;

/**
 * 生成确认收货后的退货退款所引起的退佣结算单接口 FreeMaker Template自动生成代码
 */
@TestSuite
public class Ts_GenerateRefundCommissionInvoice {

	private static GenerateRefundCommissionInvoiceBean generaterefundcommissioninvoiceBean;
	private static GenerateRefundCommissionInvoiceCall generaterefundcommissioninvoiceCall;

	private static OrderSettlementReq generateinvoicesonorderreceivedBean;
	private static GenerateInvoicesOnOrderReceivedCall generateinvoicesonorderreceivedCall;

	private static SettleSellerIncomeAndChargeCommissionBean settlesellerincomeandchargecommissionBean;
	private static SettleSellerIncomeAndChargeCommissionCall settlesellerincomeandchargecommissionCall;

	private static final BigDecimal SINGLEPRODUCTCOMMITION = BigDecimal.ZERO;// 单件商品已返佣金

	@BeforeClass
	public static void setUp() {
		Logger.createResultFile("生成确认收货后的退货退款所引起的退佣结算单接口");
	}

	@Before
	public void caseUp() {

		generaterefundcommissioninvoiceBean = new GenerateRefundCommissionInvoiceBean();
		generaterefundcommissioninvoiceCall = new GenerateRefundCommissionInvoiceCall();

		generateinvoicesonorderreceivedBean = new OrderSettlementReq();
		generateinvoicesonorderreceivedCall = new GenerateInvoicesOnOrderReceivedCall();

		settlesellerincomeandchargecommissionBean = new SettleSellerIncomeAndChargeCommissionBean();
		settlesellerincomeandchargecommissionCall = new SettleSellerIncomeAndChargeCommissionCall();

	}

	@AfterClass
	public static void tearDown() {
		Logger.generateResult(generaterefundcommissioninvoiceCall.getOpurl());
	}

	@After
	public void caseDown() {
		Logger.end();
	}

	/**
	 * 一个订单下面多个商品
	 */
	private PlaceOrderResp placeOrder(boolean isFreightFree) {

		PlaceOrderResp orderResp = new PlaceOrderResp();

		try {

			// 注册新用户
			Map newUser = new HashMap();
			newUser = new OrderCallService().registerUser();

			int userId = (Integer) newUser.get("userId");
			int sellerId = Integer.valueOf(EnvSetup.getData("SellerId"));

			PlaceOrderReq placeorderBean = PlaceOrderService
					.getDefaultOrderReq();

			placeorderBean.setUserId(userId);

			placeorderBean.setYmatouCoupon(null);

			PlaceOrderCall placeorderCall = new PlaceOrderCall();

			placeorderBean.setOrderGroups(Arrays.asList(PlaceOrderService
					.getDefaultOrderGroupVo(userId, sellerId)));

			placeorderBean.getOrderGroups().get(0).getOrders().get(0)
					.getOrderItems()
					.add(PlaceOrderService.getDefaultOrderItemVo());

			placeorderBean.getOrderGroups().get(0).getOrders().get(0)
					.getOrderItems()
					.add(PlaceOrderService.getDefaultOrderItemVo());

			int firstCataid = 1149;

			//设置没有商品的随机运费
			for (int i = 0; i < 1; i++) {

				for (int j = 0; j < 1; j++) {

					placeorderBean
							.getOrderGroups()
							.get(i)
							.getOrders()
							.get(j)
							.getOrderItems()
							.forEach(
									item -> {

										if (!isFreightFree) {

											item.setFreight(new BigDecimal(
													new Random().nextInt(50)));
										}

										item.setFirstCategoryId(firstCataid);

									});

				}

			}

			//第二个商品价格设置一个大金额，佣金收费超过最大150阀值
			OrderItemVo orderItemVo2 = placeorderBean.getOrderGroups().get(0)
					.getOrders().get(0).getOrderItems().get(1);
			orderItemVo2.setProductPrice(new BigDecimal(3100));
			orderItemVo2.setEarnestPrice(new BigDecimal(3100));
			orderItemVo2.setOriginalPrice(new BigDecimal(3100));

			placeorderCall.setData(false, placeorderBean);

			placeorderCall.callService();

			JSONArray orderArray = placeorderCall.getOrderIds();

			List<Order> orderList = new ArrayList<Order>();

			for (int i = 0; i < orderArray.length(); i++) {

				Order order = new Order();
				int orderId = orderArray.getInt(i);

				order.setOrderId(orderId);
				order.setSellerId(sellerId);

				List<OrderInfoPo> orderInfoList = new DefaultWapper()
						.selectOrderInfoByOrderId2(orderId);

				order.setOrderInfoList(orderInfoList);

				orderList.add(order);
			}

			int tradingId = placeorderCall.getTradingId();
			// 根据交易号计算需要支付的金额
			BigDecimal payAmount = new OrderCallService()
					.getNeedPrePayAmountOfCashBymainOrderId(tradingId);

			orderResp.setTradingId(tradingId);
			orderResp.setOrderList(orderList);
			orderResp.setPayAmount(payAmount);
			orderResp.setUserId(userId);

		} catch (Exception e) {
			Logger.fail(e);
		}
		return orderResp;
	}
	/**
	 * 商品部分退款
	 * 
	 * @param orderId
	 * @param money 部分退款金额
	 * @param orderCallService
	 * @return refundBillNo
	 * @throws ClientProtocolException
	 * @throws IOException
	 */
	private String partRefund(int orderId, int money,
			OrderCallService orderCallService) throws ClientProtocolException,
			IOException {
		// 申请部分退款
		ApplySalesRefundRequestBean applysalesrefundrequestBean = orderCallService
				.applySalesRefundRequestInJavaBean(orderId);
		String refundBillNo = applysalesrefundrequestBean
				.getSalesRefundInfoList().get(0).getRefundBillNo();
		String CatalogId = applysalesrefundrequestBean.getSalesRefundInfoList()
				.get(0).getCatalogId();
		String OrderInfoId = (String) new DefaultWapper()
				.selectOrderInfoByOderId(orderId).stream()
				.filter(a -> a.get("sCatalogId").equals(CatalogId))
				.collect(Collectors.toList()).get(0).get("sOrderInfoId");
		BigDecimal CommissionPerProd = calcCommissionPerProd(OrderInfoId);
		applysalesrefundrequestBean.getSalesRefundInfoList().get(0)
				.setRefundAmount(CommissionPerProd.add(new BigDecimal(money)));
		ApplySalesRefundRequestCall applysalesrefundrequestCall = new ApplySalesRefundRequestCall();
		applysalesrefundrequestCall.setData(false, applysalesrefundrequestBean);
		applysalesrefundrequestCall.callService();

		// 退款处理
		orderCallService.salesrefundsuccessrequest(applysalesrefundrequestBean);
		return refundBillNo;
	}

	/**
	 * 计算期望的单件商品实际支付金额
	 * 
	 * @param orderInfoId
	 * @return
	 */
	private BigDecimal calcCommissionPerProd(String orderInfoId) {

		BigDecimal payAmount = BigDecimal.ZERO;

		DefaultWapper defaultWapper = new DefaultWapper();

		List<Map> ymtOrderInfoList = defaultWapper
				.selectOrderInfoByOrderInfoId(orderInfoId);

		BigDecimal fProductPrice = (BigDecimal) ymtOrderInfoList.get(0).get(
				"fProductPrice");
		int iAmount = (Integer) ymtOrderInfoList.get(0).get("iAmount");

		BigDecimal fDiscount = (BigDecimal) ymtOrderInfoList.get(0).get(
				"fDiscount");
		BigDecimal fFreight = (BigDecimal) ymtOrderInfoList.get(0).get(
				"fFreight");
		BigDecimal fSellerPromotionAmount = (BigDecimal) ymtOrderInfoList
				.get(0).get("fSellerPromotionAmount");
		BigDecimal fSellerCouponAmount = (BigDecimal) ymtOrderInfoList.get(0)
				.get("fSellerCouponAmount");
		BigDecimal fYmtCouponAmount = (BigDecimal) ymtOrderInfoList.get(0).get(
				"fYmtCouponAmount");

		payAmount = fProductPrice.multiply(new BigDecimal(iAmount))
				.add(fDiscount).add(fFreight).subtract(fSellerPromotionAmount)
				.subtract(fSellerCouponAmount).subtract(fYmtCouponAmount);

		return payAmount.divide(new BigDecimal(iAmount), 2,
				BigDecimal.ROUND_HALF_UP);

	}

	@Test
	@Category({P1.class})
	@TestCase
	public void Tc_GenerateRefundCommissionInvoice_001() {
		Logger.start(true, "生成确认收货后的退货退款所引起的退佣结算单成功,单个商品全额退款");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			PlaceOrderResp placeOrderResp = placeOrder(true);

			Order order = placeOrderResp.getOrderList().get(0);

			int orderId = order.getOrderId();
			int userId = placeOrderResp.getUserId();
			int tradingId = placeOrderResp.getTradingId();
			int sellerId = order.getSellerId();
			BigDecimal totalPrice = placeOrderResp.getPayAmount();

			OrderCallService orderCallService = new OrderCallService();

			// 支付订单
			orderCallService.orderPayRequest(userId, totalPrice, tradingId);

			// 接单
			orderCallService.acceptOrder(orderId, sellerId);
			// 商家发货
			orderCallService.dispatched(orderId, sellerId);
			// 确认收货
			orderCallService.confirmReceive(userId, orderId);
			Thread.sleep(5000);
			// 确认收货时生成结算单
			generateinvoicesonorderreceivedBean.setOrderId(orderId);
			generateinvoicesonorderreceivedCall
					.setData(generateinvoicesonorderreceivedBean);
			generateinvoicesonorderreceivedCall.callService();

			// 结算收入和扣佣
			settlesellerincomeandchargecommissionBean.setOrderId(orderId);
			settlesellerincomeandchargecommissionCall
					.setData(settlesellerincomeandchargecommissionBean);
			settlesellerincomeandchargecommissionCall.callService();

			Thread.sleep(2000);

			// 第一个商品全款退款
			ApplySalesRefundRequestBean applysalesrefundrequestBean = orderCallService
					.applySalesRefundRequestInJava(orderId);
			//退款执行
			orderCallService
					.salesrefundsuccessrequest(applysalesrefundrequestBean);

			Thread.sleep(2000);
			// 生成确认收货后的退货退款所引起的退佣结算单前记录账户余额
			Map accountInfoBeforeRefundCommition = new AccountDefaultWapper()
					.selectAccountInfoByUserId(sellerId, 1).get(0);
			BigDecimal fAvailAmountBeforeRefundCommition = (BigDecimal) accountInfoBeforeRefundCommition
					.get("fAvailAmount");
			Logger.comment("前置数据准备结束");

			// 退款成功消息是异步操作，所以需要等待一段时间
			Thread.sleep(2000l);
			generaterefundcommissioninvoiceBean.setOrderId(orderId);
			GenerateRefundCommissionInvoiceBean.ParamExt paramExt = new GenerateRefundCommissionInvoiceBean.ParamExt();
			String refundBillNo = applysalesrefundrequestBean
					.getSalesRefundInfoList().get(0).getRefundBillNo();
			paramExt.setRefundBillNo(refundBillNo);
			generaterefundcommissioninvoiceBean.setParamExt(paramExt);
			generaterefundcommissioninvoiceCall
					.setData(generaterefundcommissioninvoiceBean);
			generaterefundcommissioninvoiceCall.callService();
			Logger.verifyEquals("ok",
					generaterefundcommissioninvoiceCall.getReturnData(),
					"验证返回结果");
			// 生成确认收货后的退货退款所引起的退佣结算单后记录账户余额
			Map accountInfoAfterRefundCommition = new AccountDefaultWapper()
					.selectAccountInfoByUserId(sellerId, 1).get(0);
			BigDecimal fAvailAmountAfterRefundCommition = (BigDecimal) accountInfoAfterRefundCommition
					.get("fAvailAmount");
			Logger.verifyEquals(fAvailAmountBeforeRefundCommition,
					fAvailAmountAfterRefundCommition, "验证未发生退佣结算前，余额不变");

			Map m = new HashMap();
			m.put("orderId", orderId);
			m.put("refundBillNo", refundBillNo);
			List<Map> refunds = new YmtRefundWapper().selectRefundInfo(m);
			String OrderInfoId = (String) refunds.get(0).get("OrderInfoId");
			BigDecimal RefundedAmountOfCash = (BigDecimal) refunds.get(0).get(
					"RefundedAmountOfCash"); // 退货退款单退回金额
			int RefundProductNum = (int) refunds.get(0).get("RefundProductNum"); // 可退佣金商品数量

			List<YmtCommissionDetail> details = new YmtCommissionDetailWapper()
					.selectByOrderId(orderId);
			List<YmtCommissionDetail> x = details.stream()
					.filter(a -> a.getOrderInfoId().equals(OrderInfoId))
					.collect(Collectors.toList());
			YmtCommissionDetail refundCommition = x.stream()
					.filter(a -> a.getInvoiceType() == 5)
					.collect(Collectors.toList()).get(0);
			YmtCommissionDetail billConmtion = x.stream()
					.filter(a -> a.getInvoiceType() == 4)
					.collect(Collectors.toList()).get(0);

			BigDecimal RealPayAmountPerProd = refundCommition
					.getRealPayAmount(); // 商品实际支付金额
			BigDecimal CommissionPerProd = refundCommition
					.getCommissionPerProd(); // 单件商品实际收佣金额
			BigDecimal SingleCommissionRate = refundCommition
					.getSingleCommissionRate(); // 退佣比例

			Logger.verifyEquals(billConmtion.getCommissionPerProd(),
					refundCommition.getCommissionPerProd(),
					"验证退佣的单个商品佣金CommissionPerProd");
			// 可退佣金商品数量=min[int（退货退款单退回金额/单件商品实际支付金额），退回数量]
			int expProdNumOfCommission = Integer.min(RefundedAmountOfCash
					.divide(RealPayAmountPerProd, BigDecimal.ROUND_DOWN)
					.intValue(), RefundProductNum);
			Logger.verifyEquals(expProdNumOfCommission,
					refundCommition.getProdNumOfCommission(),
					"验证Ymt_CommissionDetail表可退佣金商品数量");
			// 退回商品佣金= [单件商品实际收佣金额－单件商品已返佣金]×可退佣金商品数量×退佣比例
			BigDecimal expCommissionAmount = CommissionPerProd
					.multiply(new BigDecimal(expProdNumOfCommission))
					.multiply(SingleCommissionRate)
					.divide(BigDecimal.ONE, 2, BigDecimal.ROUND_HALF_UP);

			Logger.verifyEquals(expCommissionAmount,
					refundCommition.getCommissionAmount(),
					"验证Ymt_CommissionDetail表的退佣金额");

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({P1.class})
	@TestCase
	public void Tc_GenerateRefundCommissionInvoice_002() {
		Logger.start(true, "生成确认收货后的退货退款所引起的退佣结算单成功, "
				+ "单个商品部分退款小于单件商品实际支付金额, 退佣金额");
		try {

			PlaceOrderResp placeOrderResp = placeOrder(true);

			Order order = placeOrderResp.getOrderList().get(0);

			int orderId = order.getOrderId();
			int userId = placeOrderResp.getUserId();
			int tradingId = placeOrderResp.getTradingId();
			int sellerId = order.getSellerId();
			BigDecimal totalPrice = placeOrderResp.getPayAmount();

			OrderCallService orderCallService = new OrderCallService();

			// 支付订单
			orderCallService.orderPayRequest(userId, totalPrice, tradingId);
			orderCallService.acceptOrder(orderId, sellerId);
			// 商家发货
			orderCallService.dispatched(orderId, sellerId);
			// 确认收货
			orderCallService.confirmReceive(userId, orderId);

			// 确认收货时生成结算单
			generateinvoicesonorderreceivedBean.setOrderId(orderId);
			generateinvoicesonorderreceivedCall
					.setData(generateinvoicesonorderreceivedBean);
			generateinvoicesonorderreceivedCall.callService();

			// 结算收入和扣佣
			settlesellerincomeandchargecommissionBean.setOrderId(orderId);
			settlesellerincomeandchargecommissionCall
					.setData(settlesellerincomeandchargecommissionBean);
			settlesellerincomeandchargecommissionCall.callService();

			// 第一个商品部分退款
			String refundBillNo = partRefund(orderId, -1, orderCallService);
			// 生成确认收货后的退货退款所引起的退佣结算单前记录账户余额
			Map accountInfoBeforeRefundCommition = new AccountDefaultWapper()
					.selectAccountInfoByUserId(sellerId, 1).get(0);
			BigDecimal fAvailAmountBeforeRefundCommition = (BigDecimal) accountInfoBeforeRefundCommition
					.get("fAvailAmount");
			Logger.comment("前置数据准备结束");

			// 退款成功消息是异步操作，所以需要等待一段时间
			Thread.sleep(2000l);
			generaterefundcommissioninvoiceBean.setOrderId(orderId);
			GenerateRefundCommissionInvoiceBean.ParamExt paramExt = new GenerateRefundCommissionInvoiceBean.ParamExt();
			paramExt.setRefundBillNo(refundBillNo);
			generaterefundcommissioninvoiceBean.setParamExt(paramExt);
			generaterefundcommissioninvoiceCall
					.setData(generaterefundcommissioninvoiceBean);
			generaterefundcommissioninvoiceCall.callService();
			Logger.verifyEquals("ok",
					generaterefundcommissioninvoiceCall.getReturnData(),
					"验证返回结果");
			// 生成确认收货后的退货退款所引起的退佣结算单后记录账户余额
			Map accountInfoAfterRefundCommition = new AccountDefaultWapper()
					.selectAccountInfoByUserId(sellerId, 1).get(0);
			BigDecimal fAvailAmountAfterRefundCommition = (BigDecimal) accountInfoAfterRefundCommition
					.get("fAvailAmount");
			Logger.verifyEquals(fAvailAmountBeforeRefundCommition,
					fAvailAmountAfterRefundCommition, "验证未发生退佣结算前，余额不变");

			Map m = new HashMap();
			m.put("orderId", orderId);
			m.put("refundBillNo", refundBillNo);
			List<Map> refunds = new YmtRefundWapper().selectRefundInfo(m);
			String OrderInfoId = (String) refunds.get(0).get("OrderInfoId");

			List<YmtCommissionDetail> details = new YmtCommissionDetailWapper()
					.selectByOrderId(orderId);
			List<YmtCommissionDetail> x = details.stream()
					.filter(a -> a.getOrderInfoId().equals(OrderInfoId))
					.collect(Collectors.toList());
			YmtCommissionDetail refundCommition = x.stream()
					.filter(a -> a.getInvoiceType() == 5)
					.collect(Collectors.toList()).get(0);
			YmtCommissionDetail billConmtion = x.stream()
					.filter(a -> a.getInvoiceType() == 4)
					.collect(Collectors.toList()).get(0);

			Logger.verifyEquals(billConmtion.getCommissionPerProd(),
					refundCommition.getCommissionPerProd(),
					"验证退佣的单个商品佣金CommissionPerProd");
			// 部分退款，可退商品数量设置为0
			Logger.verifyEquals(0, refundCommition.getProdNumOfCommission(),
					"验证Ymt_CommissionDetail表可退佣金商品数量");
			// 部分退款，可退佣金金额为0.00
			Logger.verifyEquals(new BigDecimal(0.00).divide(new BigDecimal(1),
					2, BigDecimal.ROUND_HALF_UP), refundCommition
					.getCommissionAmount(), "验证Ymt_CommissionDetail表的退佣金额");

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({P1.class})
	@TestCase
	public void Tc_GenerateRefundCommissionInvoice_003() {
		Logger.start(true, "生成确认收货后的退货退款所引起的退佣结算单成功, 单个商品部分退款大于单件商品实际支付金额");
		try {

			PlaceOrderResp placeOrderResp = placeOrder(true);

			Order order = placeOrderResp.getOrderList().get(0);

			int orderId = order.getOrderId();
			int userId = placeOrderResp.getUserId();
			int tradingId = placeOrderResp.getTradingId();
			int sellerId = order.getSellerId();
			BigDecimal totalPrice = placeOrderResp.getPayAmount();

			OrderCallService orderCallService = new OrderCallService();

			// 支付订单
			orderCallService.orderPayRequest(userId, totalPrice, tradingId);
			// 接单
			orderCallService.acceptOrder(orderId, sellerId);
			// 商家发货
			orderCallService.dispatched(orderId, sellerId);
			// 确认收货
			orderCallService.confirmReceive(userId, orderId);
			// 确认收货时生成结算单
			generateinvoicesonorderreceivedBean.setOrderId(orderId);
			generateinvoicesonorderreceivedCall
					.setData(generateinvoicesonorderreceivedBean);
			generateinvoicesonorderreceivedCall.callService();
			// 结算收入和扣佣
			settlesellerincomeandchargecommissionBean.setOrderId(orderId);
			settlesellerincomeandchargecommissionCall
					.setData(settlesellerincomeandchargecommissionBean);
			settlesellerincomeandchargecommissionCall.callService();
			// 第一个商品全款退款
			String refundBillNo = partRefund(orderId, 1, orderCallService);
			// 生成确认收货后的退货退款所引起的退佣结算单前记录账户余额
			Map accountInfoBeforeRefundCommition = new AccountDefaultWapper()
					.selectAccountInfoByUserId(sellerId, 1).get(0);
			BigDecimal fAvailAmountBeforeRefundCommition = (BigDecimal) accountInfoBeforeRefundCommition
					.get("fAvailAmount");
			Logger.comment("前置数据准备结束");

			// 退款成功消息是异步操作，所以需要等待一段时间
			Thread.sleep(2000l);
			generaterefundcommissioninvoiceBean.setOrderId(orderId);
			GenerateRefundCommissionInvoiceBean.ParamExt paramExt = new GenerateRefundCommissionInvoiceBean.ParamExt();
			paramExt.setRefundBillNo(refundBillNo);
			generaterefundcommissioninvoiceBean.setParamExt(paramExt);
			generaterefundcommissioninvoiceCall
					.setData(generaterefundcommissioninvoiceBean);
			generaterefundcommissioninvoiceCall.callService();
			Logger.verifyEquals("ok",
					generaterefundcommissioninvoiceCall.getReturnData(),
					"验证返回结果");
			// 生成确认收货后的退货退款所引起的退佣结算单后记录账户余额
			Map accountInfoAfterRefundCommition = new AccountDefaultWapper()
					.selectAccountInfoByUserId(sellerId, 1).get(0);
			BigDecimal fAvailAmountAfterRefundCommition = (BigDecimal) accountInfoAfterRefundCommition
					.get("fAvailAmount");
			Logger.verifyEquals(fAvailAmountBeforeRefundCommition,
					fAvailAmountAfterRefundCommition, "验证未发生退佣结算前，余额不变");

			Map m = new HashMap();
			m.put("orderId", orderId);
			m.put("refundBillNo", refundBillNo);
			List<Map> refunds = new YmtRefundWapper().selectRefundInfo(m);
			String OrderInfoId = (String) refunds.get(0).get("OrderInfoId");
			BigDecimal RefundedAmountOfCash = (BigDecimal) refunds.get(0).get(
					"RefundedAmountOfCash"); // 退货退款单退回金额
			int RefundProductNum = (int) refunds.get(0).get("RefundProductNum"); // 可退佣金商品数量

			List<YmtCommissionDetail> details = new YmtCommissionDetailWapper()
					.selectByOrderId(orderId);
			List<YmtCommissionDetail> x = details.stream()
					.filter(a -> a.getOrderInfoId().equals(OrderInfoId))
					.collect(Collectors.toList());
			YmtCommissionDetail refundCommition = x.stream()
					.filter(a -> a.getInvoiceType() == 5)
					.collect(Collectors.toList()).get(0);
			YmtCommissionDetail billConmtion = x.stream()
					.filter(a -> a.getInvoiceType() == 4)
					.collect(Collectors.toList()).get(0);

			BigDecimal RealPayAmountPerProd = refundCommition
					.getRealPayAmountPerProd(); // 单件商品实际支付金额
			BigDecimal CommissionPerProd = refundCommition
					.getCommissionPerProd(); // 单件商品实际收佣金额
			BigDecimal SingleCommissionRate = refundCommition
					.getSingleCommissionRate(); // 退佣比例

			Logger.verifyEquals(billConmtion.getCommissionPerProd(),
					refundCommition.getCommissionPerProd(),
					"验证退佣的单个商品佣金CommissionPerProd");
			// 可退佣金商品数量=min[int（退货退款单退回金额/单件商品实际支付金额），退回数量]
			int expProdNumOfCommission = Integer.min(RefundedAmountOfCash
					.divide(RealPayAmountPerProd, BigDecimal.ROUND_DOWN)
					.intValue(), RefundProductNum);
			Logger.verifyEquals(expProdNumOfCommission,
					refundCommition.getProdNumOfCommission(),
					"验证Ymt_CommissionDetail表可退佣金商品数量");
			// 退回商品佣金= [单件商品实际收佣金额－单件商品已返佣金]×可退佣金商品数量×退佣比例
			BigDecimal expCommissionAmount = CommissionPerProd
					.multiply(new BigDecimal(expProdNumOfCommission))
					.multiply(SingleCommissionRate)
					.divide(new BigDecimal(1), 2, BigDecimal.ROUND_HALF_UP);
			Logger.verifyEquals(expCommissionAmount,
					refundCommition.getCommissionAmount(),
					"验证Ymt_CommissionDetail表的退佣金额");

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({P1.class})
	@TestCase
	public void Tc_GenerateRefundCommissionInvoice_004() {
		Logger.start(true, "老买手,老客户，生成确认收货后，已返佣金，退货退款不退拥金");
		try {
			PlaceOrderResp placeOrderResp = SettlementService.placeOrder2(true);

			Order order = placeOrderResp.getOrderList().get(0);

			int orderId = order.getOrderId();
			int userId = placeOrderResp.getUserId();
			int tradingId = placeOrderResp.getTradingId();
			int sellerId = order.getSellerId();
			BigDecimal payAmount = placeOrderResp.getPayAmount();

			OrderCallService orderCallService = new OrderCallService();

			// 支付订单
			orderCallService.orderPayRequest(userId, payAmount, tradingId);

			// 接单
			orderCallService.acceptOrder(orderId, sellerId);
			// 商家发货
			orderCallService.dispatched(orderId, sellerId);
			// 确认收货
			orderCallService.confirmReceive(userId, orderId);
			Thread.sleep(5000);
			// 确认收货时生成结算单
			generateinvoicesonorderreceivedBean.setOrderId(orderId);
			generateinvoicesonorderreceivedCall
					.setData(generateinvoicesonorderreceivedBean);
			generateinvoicesonorderreceivedCall.callService();
			// 结算收入和扣佣
			settlesellerincomeandchargecommissionBean.setOrderId(orderId);
			settlesellerincomeandchargecommissionCall
					.setData(settlesellerincomeandchargecommissionBean);
			// settlesellerincomeandchargecommissionCall.callService();

			// 第一个商品全款退款            
			ApplySalesRefundRequestBean applysalesrefundrequestBean = orderCallService
					.applySalesRefundRequestInJava(orderId);

			orderCallService
					.salesrefundsuccessrequest(applysalesrefundrequestBean);

			Thread.sleep(5000);
			// 生成确认收货后的退货退款所引起的退佣结算单前记录账户余额
			Map accountInfoBeforeRefundCommition = new AccountDefaultWapper()
					.selectAccountInfoByUserId(sellerId, 1).get(0);
			BigDecimal fAvailAmountBeforeRefundCommition = (BigDecimal) accountInfoBeforeRefundCommition
					.get("fAvailAmount");
			Logger.comment("前置数据准备结束");

			// 退款成功消息是异步操作，所以需要等待一段时间
			Thread.sleep(2000l);
			generaterefundcommissioninvoiceBean.setOrderId(orderId);
			GenerateRefundCommissionInvoiceBean.ParamExt paramExt = new GenerateRefundCommissionInvoiceBean.ParamExt();
			String refundBillNo = applysalesrefundrequestBean
					.getSalesRefundInfoList().get(0).getRefundBillNo();
			paramExt.setRefundBillNo(refundBillNo);
			generaterefundcommissioninvoiceBean.setParamExt(paramExt);
			generaterefundcommissioninvoiceCall
					.setData(generaterefundcommissioninvoiceBean);
			generaterefundcommissioninvoiceCall.callService();
			Logger.verifyEquals("ok",
					generaterefundcommissioninvoiceCall.getReturnData(),
					"验证返回结果");
			// 生成确认收货后的退货退款所引起的退佣结算单后记录账户余额
			Map accountInfoAfterRefundCommition = new AccountDefaultWapper()
					.selectAccountInfoByUserId(sellerId, 1).get(0);
			BigDecimal fAvailAmountAfterRefundCommition = (BigDecimal) accountInfoAfterRefundCommition
					.get("fAvailAmount");
			Logger.verifyEquals(fAvailAmountBeforeRefundCommition,
					fAvailAmountAfterRefundCommition, "验证未发生退佣结算前，余额不变");

			Map m = new HashMap();
			m.put("orderId", orderId);
			m.put("refundBillNo", refundBillNo);

			List<Map> refunds = new YmtRefundWapper().selectRefundInfo(m);

			String OrderInfoId = (String) refunds.get(0).get("OrderInfoId");

			BigDecimal RefundedAmountOfCash = (BigDecimal) refunds.get(0).get(
					"RefundedAmountOfCash"); // 退货退款单退回金额
			int RefundProductNum = (int) refunds.get(0).get("RefundProductNum"); // 可退佣金商品数量
			// 结算表
			List<Map> settlementInvoiceList = new DefaultWapper()
					.selectYmtSettlementInvoice(orderId);

			List<YmtCommissionDetail> details = new YmtCommissionDetailWapper()
					.selectByOrderId(orderId);
			List<YmtCommissionDetail> x = details.stream()
					.filter(a -> a.getOrderInfoId().equals(OrderInfoId))
					.collect(Collectors.toList());
			YmtCommissionDetail billConmtion = x.stream()
					.filter(a -> a.getInvoiceType() == 4)
					.collect(Collectors.toList()).get(0);

			Logger.verifyEquals(
					0,
					settlementInvoiceList
							.stream()
							.filter(commission -> (Integer) commission
									.get("BusinessType") == 5)
							.collect(Collectors.toList()).size(),
					"验证Ymt_SettlementInvoice表没有退佣结算");
		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({P1.class})
	@TestCase
	public void Tc_GenerateRefundCommissionInvoice_005() {
		Logger.start(true, "带运费的商品订单，确认收货后，多个商品申请退款,校验退佣结算单");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			PlaceOrderResp placeOrderResp = placeOrder(false);

			Order order = placeOrderResp.getOrderList().get(0);

			int orderId = order.getOrderId();
			int userId = placeOrderResp.getUserId();
			int tradingId = placeOrderResp.getTradingId();
			int sellerId = order.getSellerId();
			BigDecimal payAmount = placeOrderResp.getPayAmount();

			OrderCallService orderCallService = new OrderCallService();

			// 支付订单
			orderCallService.orderPayRequest(userId, payAmount, tradingId);
			// 接单
			orderCallService.acceptOrder(orderId, sellerId);
			// 商家发货
			orderCallService.dispatched(orderId, sellerId);

			// 确认收货
			orderCallService.confirmReceive(userId, orderId);

			// 部分退款
			OrderInfoPo orderInfoPo1 = order.getOrderInfoList().get(0);
			OrderInfoPo orderInfoPo2 = order.getOrderInfoList().get(1);

			BigDecimal partRefund1 = SettlementService
					.calcRealPayAmountOnProduct(orderInfoPo1.getOrderInfoId())
					.add(BigDecimal.ONE);

			BigDecimal partRefund2 = SettlementService
					.calcRealPayAmountOnProduct(orderInfoPo2.getOrderInfoId())
					.add(BigDecimal.ONE);

			ApplySalesRefundRequestBean applySalesRefundRequestBean = orderCallService
					.applySalesRefundRequestInJavaBean(orderId);

			applySalesRefundRequestBean.getSalesRefundInfoList().remove(2);

			applySalesRefundRequestBean.getSalesRefundInfoList().get(0)
					.setRefundAmount(partRefund1);

			applySalesRefundRequestBean.getSalesRefundInfoList().get(1)
					.setRefundAmount(partRefund2);

			orderCallService
					.applySalesRefundRequestCall(applySalesRefundRequestBean);
			//退款执行
			orderCallService
					.salesrefundsuccessrequest(applySalesRefundRequestBean);

			Thread.sleep(5000);

			// 结算收入和扣佣
			settlesellerincomeandchargecommissionBean.setOrderId(orderId);
			settlesellerincomeandchargecommissionCall
					.setData(settlesellerincomeandchargecommissionBean);
			settlesellerincomeandchargecommissionCall.callService();

			Thread.sleep(2000);

			// 生成确认收货后的退货退款所引起的退佣结算单前记录账户余额
			Map accountInfoBeforeRefundCommition = new AccountDefaultWapper()
					.selectAccountInfoByUserId(sellerId, 1).get(0);
			BigDecimal fAvailAmountBeforeRefundCommition = (BigDecimal) accountInfoBeforeRefundCommition
					.get("fAvailAmount");
			Logger.comment("前置数据准备结束");

			// 退款成功消息是异步操作，所以需要等待一段时间
			Thread.sleep(2000l);
			generaterefundcommissioninvoiceBean.setOrderId(orderId);

			GenerateRefundCommissionInvoiceBean.ParamExt paramExt = new GenerateRefundCommissionInvoiceBean.ParamExt();
			String refundBillNo = applySalesRefundRequestBean
					.getSalesRefundInfoList().get(0).getRefundBillNo();

			paramExt.setRefundBillNo(refundBillNo);

			generaterefundcommissioninvoiceBean.setParamExt(paramExt);
			generaterefundcommissioninvoiceCall
					.setData(generaterefundcommissioninvoiceBean);
			generaterefundcommissioninvoiceCall.callService();

			Logger.verifyEquals("ok",
					generaterefundcommissioninvoiceCall.getReturnData(),
					"验证返回结果");
			SettlementService.generateRefund(applySalesRefundRequestBean
					.getSalesRefundInfoList().get(1).getRefundBillNo());

			// 生成确认收货后的退货退款所引起的退佣结算单后记录账户余额
			Map accountInfoAfterRefundCommition = new AccountDefaultWapper()
					.selectAccountInfoByUserId(sellerId, 1).get(0);
			BigDecimal fAvailAmountAfterRefundCommition = (BigDecimal) accountInfoAfterRefundCommition
					.get("fAvailAmount");
			Logger.verifyEquals(fAvailAmountBeforeRefundCommition,
					fAvailAmountAfterRefundCommition, "验证未发生退佣结算前，余额不变");

			Map m = new HashMap();
			m.put("orderId", orderId);
			m.put("refundBillNo", refundBillNo);
			List<Map> refunds = new YmtRefundWapper().selectRefundInfo(m);
			String OrderInfoId = (String) refunds.get(0).get("OrderInfoId");
			BigDecimal RefundedAmountOfCash = (BigDecimal) refunds.get(0).get(
					"RefundedAmountOfCash"); // 退货退款单退回金额
			int RefundProductNum = (int) refunds.get(0).get("RefundProductNum"); // 可退佣金商品数量

			List<YmtCommissionDetail> details = new YmtCommissionDetailWapper()
					.selectByOrderId(orderId);
			List<YmtCommissionDetail> x = details.stream()
					.filter(a -> a.getOrderInfoId().equals(OrderInfoId))
					.collect(Collectors.toList());
			YmtCommissionDetail refundCommition = x.stream()
					.filter(a -> a.getInvoiceType() == 5)
					.collect(Collectors.toList()).get(0);
			YmtCommissionDetail billConmtion = x.stream()
					.filter(a -> a.getInvoiceType() == 4)
					.collect(Collectors.toList()).get(0);

			BigDecimal RealPayAmountPerProd = refundCommition
					.getRealPayAmountPerProd(); // 单件商品实际支付金额
			BigDecimal CommissionPerProd = refundCommition
					.getCommissionPerProd(); // 单件商品实际收佣金额
			BigDecimal SingleCommissionRate = refundCommition
					.getSingleCommissionRate(); // 退佣比例

			Logger.verifyEquals(billConmtion.getCommissionPerProd(),
					refundCommition.getCommissionPerProd(),
					"验证退佣的单个商品佣金CommissionPerProd");

			// 可退佣金商品数量=min[int（退货退款单退回金额/单件商品实际支付金额），退回数量]
			int expProdNumOfCommission = Integer.min(RefundedAmountOfCash
					.divide(RealPayAmountPerProd, BigDecimal.ROUND_DOWN)
					.intValue(), RefundProductNum);

			Logger.verifyEquals(expProdNumOfCommission,
					refundCommition.getProdNumOfCommission(),
					"验证Ymt_CommissionDetail表可退佣金商品数量");
			// 退回商品佣金= [单件商品实际收佣金额－单件商品已返佣金]×可退佣金商品数量×退佣比例
			BigDecimal expCommissionAmount = CommissionPerProd
					.multiply(new BigDecimal(expProdNumOfCommission))
					.multiply(SingleCommissionRate)
					.divide(new BigDecimal(1), 2, BigDecimal.ROUND_HALF_UP);
			Logger.verifyEquals(expCommissionAmount,
					refundCommition.getCommissionAmount(),
					"验证Ymt_CommissionDetail表的退佣金额");

		} catch (Exception e) {
			Logger.fail(e);
		}
	}

	@Test
	@Category({P1.class})
	@TestCase
	public void Tc_GenerateRefundCommissionInvoice_006() {
		Logger.start(true, "带运费的商品订单，确认收货前退一件，确认收货后在退一件,校验退佣结算单");
		try {
			// 创建订单
			Logger.comment("前置数据准备");

			PlaceOrderResp placeOrderResp = placeOrder(false);

			Order order = placeOrderResp.getOrderList().get(0);

			int orderId = order.getOrderId();
			int userId = placeOrderResp.getUserId();
			int tradingId = placeOrderResp.getTradingId();
			int sellerId = order.getSellerId();
			BigDecimal payAmount = placeOrderResp.getPayAmount();

			OrderCallService orderCallService = new OrderCallService();

			// 支付订单
			orderCallService.orderPayRequest(userId, payAmount, tradingId);
			// 接单
			orderCallService.acceptOrder(orderId, sellerId);
			// 商家发货
			orderCallService.dispatched(orderId, sellerId);

			OrderInfoPo orderInfoPo1 = order.getOrderInfoList().get(0);

			BigDecimal partRefund1 = SettlementService
					.calcRealPayAmountOnProduct(orderInfoPo1.getOrderInfoId())
					.add(BigDecimal.ONE);

			ApplySalesRefundRequestBean applySalesRefundRequestBean = orderCallService
					.applySalesRefundRequestInJavaBean(orderId);

			applySalesRefundRequestBean.getSalesRefundInfoList().remove(1);

			applySalesRefundRequestBean.getSalesRefundInfoList().remove(1);

			applySalesRefundRequestBean.getSalesRefundInfoList().get(0)
					.setRefundAmount(partRefund1);

			orderCallService
					.applySalesRefundRequestCall(applySalesRefundRequestBean);
			//退款执行
			orderCallService
					.salesrefundsuccessrequest(applySalesRefundRequestBean);

			// 确认收货
			orderCallService.confirmReceive(userId, orderId);

			// 部分退款

			OrderInfoPo orderInfoPo2 = order.getOrderInfoList().get(1);

			BigDecimal partRefund2 = SettlementService
					.calcRealPayAmountOnProduct(orderInfoPo2.getOrderInfoId())
					.add(BigDecimal.ONE);

			applySalesRefundRequestBean = new ApplySalesRefundRequestBean();

			applySalesRefundRequestBean.setOrderId(orderId);

			SalesRefundInfoBean salesRefundInfoBean = new SalesRefundInfoBean();

			salesRefundInfoBean.setApprover("autotest");
			salesRefundInfoBean.setCatalogId(orderInfoPo2.getCatalogId());
			salesRefundInfoBean.setReason("test");
			salesRefundInfoBean.setRefundBillNo("TH1" + orderId);
			salesRefundInfoBean.setRefundAmount(partRefund2);
			salesRefundInfoBean.setRefundProductNum(orderInfoPo2.getAmount());

			applySalesRefundRequestBean.setSalesRefundInfoList(Arrays
					.asList(salesRefundInfoBean));

			orderCallService
					.applySalesRefundRequestCall(applySalesRefundRequestBean);

			//退款执行
			orderCallService
					.salesrefundsuccessrequest(applySalesRefundRequestBean);

			Thread.sleep(5000);

			// 结算收入和扣佣
			settlesellerincomeandchargecommissionBean.setOrderId(orderId);
			settlesellerincomeandchargecommissionCall
					.setData(settlesellerincomeandchargecommissionBean);
			settlesellerincomeandchargecommissionCall.callService();

			Thread.sleep(2000);

			// 生成确认收货后的退货退款所引起的退佣结算单前记录账户余额
			Map accountInfoBeforeRefundCommition = new AccountDefaultWapper()
					.selectAccountInfoByUserId(sellerId, 1).get(0);
			BigDecimal fAvailAmountBeforeRefundCommition = (BigDecimal) accountInfoBeforeRefundCommition
					.get("fAvailAmount");
			Logger.comment("前置数据准备结束");

			// 退款成功消息是异步操作，所以需要等待一段时间
			Thread.sleep(2000);
			generaterefundcommissioninvoiceBean.setOrderId(orderId);

			GenerateRefundCommissionInvoiceBean.ParamExt paramExt = new GenerateRefundCommissionInvoiceBean.ParamExt();
			String refundBillNo = applySalesRefundRequestBean
					.getSalesRefundInfoList().get(0).getRefundBillNo();

			paramExt.setRefundBillNo(refundBillNo);

			generaterefundcommissioninvoiceBean.setParamExt(paramExt);
			generaterefundcommissioninvoiceCall
					.setData(generaterefundcommissioninvoiceBean);
			generaterefundcommissioninvoiceCall.callService();

			Logger.verifyEquals("ok",
					generaterefundcommissioninvoiceCall.getReturnData(),
					"验证返回结果");

			// 生成确认收货后的退货退款所引起的退佣结算单后记录账户余额
			Map accountInfoAfterRefundCommition = new AccountDefaultWapper()
					.selectAccountInfoByUserId(sellerId, 1).get(0);
			BigDecimal fAvailAmountAfterRefundCommition = (BigDecimal) accountInfoAfterRefundCommition
					.get("fAvailAmount");
			Logger.verifyEquals(fAvailAmountBeforeRefundCommition,
					fAvailAmountAfterRefundCommition, "验证未发生退佣结算前，余额不变");

			Map m = new HashMap();
			m.put("orderId", orderId);
			m.put("refundBillNo", refundBillNo);
			List<Map> refunds = new YmtRefundWapper().selectRefundInfo(m);
			String OrderInfoId = (String) refunds.get(0).get("OrderInfoId");
			BigDecimal RefundedAmountOfCash = (BigDecimal) refunds.get(0).get(
					"RefundedAmountOfCash"); // 退货退款单退回金额
			int RefundProductNum = (int) refunds.get(0).get("RefundProductNum"); // 可退佣金商品数量

			List<YmtCommissionDetail> details = new YmtCommissionDetailWapper()
					.selectByOrderId(orderId);
			List<YmtCommissionDetail> x = details.stream()
					.filter(a -> a.getOrderInfoId().equals(OrderInfoId))
					.collect(Collectors.toList());
			YmtCommissionDetail refundCommition = x.stream()
					.filter(a -> a.getInvoiceType() == 5)
					.collect(Collectors.toList()).get(0);
			YmtCommissionDetail billConmtion = x.stream()
					.filter(a -> a.getInvoiceType() == 4)
					.collect(Collectors.toList()).get(0);

			BigDecimal RealPayAmountPerProd = refundCommition
					.getRealPayAmountPerProd(); // 单件商品实际支付金额
			BigDecimal CommissionPerProd = refundCommition
					.getCommissionPerProd(); // 单件商品实际收佣金额
			BigDecimal SingleCommissionRate = refundCommition
					.getSingleCommissionRate(); // 退佣比例

			Logger.verifyEquals(billConmtion.getCommissionPerProd(),
					refundCommition.getCommissionPerProd(),
					"验证退佣的单个商品佣金CommissionPerProd");

			// 可退佣金商品数量=min[int（退货退款单退回金额/单件商品实际支付金额），退回数量]
			int expProdNumOfCommission = Integer.min(RefundedAmountOfCash
					.divide(RealPayAmountPerProd, BigDecimal.ROUND_DOWN)
					.intValue(), RefundProductNum);

			Logger.verifyEquals(expProdNumOfCommission,
					refundCommition.getProdNumOfCommission(),
					"验证Ymt_CommissionDetail表可退佣金商品数量");
			// 退回商品佣金= [单件商品实际收佣金额－单件商品已返佣金]×可退佣金商品数量×退佣比例
			BigDecimal expCommissionAmount = CommissionPerProd
					.multiply(new BigDecimal(expProdNumOfCommission))
					.multiply(SingleCommissionRate)
					.divide(new BigDecimal(1), 2, BigDecimal.ROUND_HALF_UP);
			Logger.verifyEquals(expCommissionAmount,
					refundCommition.getCommissionAmount(),
					"验证Ymt_CommissionDetail表的退佣金额");

		} catch (Exception e) {
			Logger.fail(e);
		}
	}
}
